マルチアカウントにAWS CLIを実行してみた
こんにちは。たかやまです。
マルチアカウント環境のリソースを確認するとき皆さんどうされますか?
Organizations環境であればAWS Configを使った高度なクエリでリソースを検索することができます。
ただ、AWS Configの高度なクエリはSQL文を利用する必要があったり、検索できるリソースタイプが限られています。
普段AWS CLIでリソースを確認している場合には、そのままマルチアカウントにAWS CLIでリソースを確認したいという要望もあるかと思います。
(ターミナルのブロードキャストコマンドのようなイメージ)
そこで今回はAWS CLIでマルチアカウントのリソースを確認する方法を紹介します。
検証環境
検証環境の全体構成はこちらです
やってみる
クロスアカウントロールを設定する
まずマルチアカウントにAWS CLIを実行するために、必要な権限を持ったクロスアカウントロールを作成していきます。ここでは、ReadOnly権限を持ったクロスアカウントロールを作成します。
<Your Management Account>
には、マルチアカウントの管理アカウントのIDを入力してください。
AWSTemplateFormatVersion: "2010-09-09" Resources: CrossAccountAccessRole: Type: "AWS::IAM::Role" Properties: RoleName: CrossAccountAccessRole AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: arn:aws:iam::<Your Management Account>:root # Replace with the your management account ID Action: "sts:AssumeRole" ManagedPolicyArns: - "arn:aws:iam::aws:policy/ReadOnlyAccess" Path: "/" Description: "IAM role with ReadOnly permissions for cross-account access." Outputs: RoleARN: Description: "The ARN of the created IAM Role" Value: !GetAtt CrossAccountAccessRole.Arn
Organizations環境であれば、CloudFormation StackSetsを利用して、マルチアカウントにクロスアカウントロールを作成することができます。
yamlファイルをローカルに配置した状態で以下のコマンドを実行することでスタックセットを作成します。
aws cloudformation create-stack-set \ --stack-set-name cross-account-access-role-stackset \ --template-body file://cross-account-access-role.yaml \ --permission-model SERVICE_MANAGED \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false \ --capabilities CAPABILITY_NAMED_IAM
次に、以下のコマンドでスタックインスタンスを作成します。
r-xxx
はOrganizationsのRootのUnitIdを入力してください。
aws cloudformation create-stack-instances \ --stack-set-name cross-account-access-role-stackset \ --operation-preferences FailureTolerancePercentage=100,MaxConcurrentPercentage=100,ConcurrencyMode=SOFT_FAILURE_TOLERANCE \ --deployment-targets OrganizationalUnitIds='["r-xxxx"]' \ --regions '["ap-northeast-1"]'
スタックインスタンスが無事作成されたら、AWS CLIをマルチアカウントに実行するための準備は完了です。
マルチアカウントに対してAWS CLIを実行する
以下のスクリプトを利用して、マルチアカウントに対してAWS CLIを実行していきます。
おおまかな処理として、aws organizations list-accounts
で取得したアカウントIDに対して、aws sts assume-role
でさきほど作成したクロスアカウントロールの一時クレデンシャルを取得してAWS CLIを実行しています。
(Organizations環境外のアカウントに対してAWS CLIを実行する場合にはコメントアウトしているaccount_ids=(xxxxxxxxxxxx xxxxxxxxxxx)
にアカウントIDをハードコードして利用してください)
処理時間短縮のために、コマンドは並列実行しています。アカウント数が多い場合はCPU負荷が高くなるため、高負荷を許容できない場合には直列実行版のスクリプトを利用することをおすすめします。
#!/bin/bash # Gets the current AWS account ID. admin_account_id=$(aws sts get-caller-identity --query "Account" --output text) # Prompts the user for input: AWS command, account ID, and region. read -rp "Enter the AWS command you want to execute: " command read -rp "Enter the account ID to execute on (default: all accounts): " specific_account_id read -rp "Enter the region to execute in (default: all regions): " specific_region echo # Gets a list of member account IDs. if [[ -z "${specific_account_id}" ]]; then read -ra account_ids <<<"$(aws organizations list-accounts --query "Accounts[?Status=='ACTIVE'].Id" --output text)" # account_ids=(xxxxxxxxxxxx xxxxxxxxxxx) else account_ids=("${specific_account_id}") fi # Gets a list of all available regions. if [[ -z "${specific_region}" ]]; then read -ra regions <<<"$(aws ec2 describe-regions --query "Regions[].RegionName" --output text)" else regions=("${specific_region}") fi # Creates a directory to store temporary files. tmp_dir=$(mktemp -d) trap 'rm -rf "${tmp_dir}"' EXIT # Executes the command for each account and region in parallel. for account_id in "${account_ids[@]}"; do for region in "${regions[@]}"; do tmp_file="${tmp_dir}/output_${account_id}_${region}.txt" ( if [[ "${account_id}" != "${admin_account_id}" ]]; then role_arn="arn:aws:iam::${account_id}:role/CrossAccountAccessRole" assume_role_output=$(aws sts assume-role --role-arn "${role_arn}" --role-session-name "CrossAccountSession") access_key_id=$(echo "${assume_role_output}" | jq -r '.Credentials.AccessKeyId') secret_access_key=$(echo "${assume_role_output}" | jq -r '.Credentials.SecretAccessKey') session_token=$(echo "${assume_role_output}" | jq -r '.Credentials.SessionToken') AWS_ACCESS_KEY_ID=${access_key_id} AWS_SECRET_ACCESS_KEY=${secret_access_key} AWS_SESSION_TOKEN=${session_token} eval "${command} --region ${region}" &>>"${tmp_file}" else eval "${command} --region ${region}" &>>"${tmp_file}" fi ) & done done # Waits for all background processes to complete. wait # Outputs the results from the temporary files in order. current_account_id="" for account_id in "${account_ids[@]}"; do if [[ "${current_account_id}" != "${account_id}" ]]; then echo "# Account ID: ${account_id}" current_account_id=${account_id} fi for region in "${regions[@]}"; do tmp_file="${tmp_dir}/output_${account_id}_${region}.txt" if [[ -f "${tmp_file}" ]]; then echo "## Region: ${region}" cat "${tmp_file}" echo fi done done # Temporary directory deletion is handled by the trap. echo "All commands have been executed."
直列実行版
#!/bin/bash # Gets the current AWS account ID. admin_account_id=$(aws sts get-caller-identity --query "Account" --output text) # Prompts the user for input: AWS command, account ID, and region. read -rp "Enter the AWS command you want to execute: " command read -rp "Enter the account ID to execute on (default: all accounts): " specific_account_id read -rp "Enter the region to execute in (default: all regions): " specific_region echo # Gets a list of member account IDs. if [[ -z "${specific_account_id}" ]]; then read -ra account_ids <<<"$(aws organizations list-accounts --query "Accounts[?Status=='ACTIVE'].Id" --output text)" # account_ids=(xxxxxxxxxxxx xxxxxxxxxxx) else account_ids=("${specific_account_id}") fi # Gets a list of all available regions. if [[ -z "${specific_region}" ]]; then read -ra regions <<<"$(aws ec2 describe-regions --query "Regions[].RegionName" --output text)" else regions=("${specific_region}") fi # Executes the command for each account and region in series. for account_id in "${account_ids[@]}"; do echo "# Account ID: ${account_id}" for region in "${regions[@]}"; do echo "## Region: ${region}" if [[ "${account_id}" != "${admin_account_id}" ]]; then role_arn="arn:aws:iam::${account_id}:role/CrossAccountAccessRole" assume_role_output=$(aws sts assume-role --role-arn "${role_arn}" --role-session-name "CrossAccountSession") access_key_id=$(echo "${assume_role_output}" | jq -r '.Credentials.AccessKeyId') secret_access_key=$(echo "${assume_role_output}" | jq -r '.Credentials.SecretAccessKey') session_token=$(echo "${assume_role_output}" | jq -r '.Credentials.SessionToken') AWS_ACCESS_KEY_ID=${access_key_id} AWS_SECRET_ACCESS_KEY=${secret_access_key} AWS_SESSION_TOKEN=${session_token} eval "${command} --region ${region}" else eval "${command} --region ${region}" fi echo done done echo "All commands have been executed."
スクリプト内で以下3つの入力を受け付けるようにしています。
- Enter the AWS command you want to execute:
- Enter the account ID to execute on (default: all accounts):
- Enter the region to execute in (default: all regions):
実際にこちらのスクリプトを利用して、マルチアカウントのAWS Configの設定を確認してみたいと思います。
パラメータとしては以下のように入力しています。
- Enter the AWS command you want to execute:
aws configservice describe-configuration-recorder-status --query ConfigurationRecordersStatus[].recording --output text
- Enter the account ID to execute on (default: all accounts):
- Enter the region to execute in (default: all regions):
Enter the AWS command you want to execute: aws configservice describe-configuration-recorder-status --query ConfigurationRecordersStatus[].recording --output text Enter the account ID to execute on (default: all accounts): Enter the region to execute in (default: all regions): # Account ID: 27xxxxxxxx75 ## Region: ap-south-1 True ## Region: eu-north-1 True ## Region: eu-west-3 True ## Region: eu-west-2 True ## Region: eu-west-1 True ## Region: ap-northeast-3 True ## Region: ap-northeast-2 True ## Region: ap-northeast-1 True ## Region: ca-central-1 True ## Region: sa-east-1 True ## Region: ap-southeast-1 True ## Region: ap-southeast-2 True ## Region: eu-central-1 True ## Region: us-east-1 True ## Region: us-east-2 True ## Region: us-west-1 True ## Region: us-west-2 True # Account ID: 80xxxxxxxx71 ## Region: ap-south-1 True ## Region: eu-north-1 True ## Region: eu-west-3 True ## Region: eu-west-2 True ## Region: eu-west-1 True ## Region: ap-northeast-3 True ## Region: ap-northeast-2 True ## Region: ap-northeast-1 True ## Region: ca-central-1 True ## Region: sa-east-1 True ## Region: ap-southeast-1 True ## Region: ap-southeast-2 True ## Region: eu-central-1 True ## Region: us-east-1 True ## Region: us-east-2 True ## Region: us-west-1 True ## Region: us-west-2 True # Account ID: 77xxxxxxxx59 ## Region: ap-south-1 True ## Region: eu-north-1 True ## Region: eu-west-3 True ## Region: eu-west-2 True ## Region: eu-west-1 True ## Region: ap-northeast-3 True ## Region: ap-northeast-2 True ## Region: ap-northeast-1 True ## Region: ca-central-1 True ## Region: sa-east-1 True ## Region: ap-southeast-1 True ## Region: ap-southeast-2 True ## Region: eu-central-1 True ## Region: us-east-1 True ## Region: us-east-2 True ## Region: us-west-1 True ## Region: us-west-2 True # Account ID: 74xxxxxxxx44 ## Region: ap-south-1 True ## Region: eu-north-1 True ## Region: eu-west-3 True ## Region: eu-west-2 True ## Region: eu-west-1 True ## Region: ap-northeast-3 True ## Region: ap-northeast-2 True ## Region: ap-northeast-1 True ## Region: ca-central-1 True ## Region: sa-east-1 True ## Region: ap-southeast-1 True ## Region: ap-southeast-2 True ## Region: eu-central-1 True ## Region: us-east-1 True ## Region: us-east-2 True ## Region: us-west-1 True ## Region: us-west-2 True All commands have been executed.
4アカウントの全リージョンのAWS Configの設定を確認することができました。
以下のように特定アカウントの、特定リージョンのAWS Configの設定を確認することもできます。
- Enter the AWS command you want to execute:
aws configservice describe-configuration-recorder-status --query ConfigurationRecordersStatus[].recording --output text
- Enter the account ID to execute on (default: all accounts):
27xxxxxxxx75
- Enter the region to execute in (default: all regions):
ap-northeast-1
Enter the AWS command you want to execute: aws configservice describe-configuration-recorder-status --query ConfigurationRecordersStatus[].recording --output text Enter the account ID to execute on (default: all accounts): 27xxxxxxxx75 Enter the region to execute in (default: all regions): ap-northeast-1 # Account ID: 27xxxxxxxx75 ## Region: ap-northeast-1 True All commands have been executed.
最後に
今回はAWS CLIでマルチアカウントのリソースを確認する方法を紹介しました。
クロスアカウントロールを用意することで、AWS CLIでマルチアカウントのリソースを確認することができるようになります。
多数のアカウントに対してコマンド打ちたい場合などに、ぜひご活用してみてください。
以上、たかやま(@nyan_kotaroo)でした。